package models

import (
	"bytes"
	"database/sql"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/cache"
	"github.com/astaxie/beego/orm"
	"github.com/pquerna/ffjson/ffjson"
	"os"
	"strconv"
	"time"
)

var dataconfigcache, _ = cache.NewCache("memory", `{"interval":600}`)
var datacachePrefix = "dataconfig"

const cachTime = 600 * time.Second

type DataConfig struct {
	Id             int64  `form:"id" orm:"column(id)" json:"id"`
	DataJson       string `form:"data_json" orm:"column(data_json)" json:"data_json"`
	DataType       string `form:"data_type" orm:"column(data_type)" json:"data_type"`
	DataNo         string `form:"data_no" orm:"column(data_no)" json:"data_no"`
	Creator        string `form:"creator" orm:"column(creator)" json:"creator"`
	CreateTime     string `form:"createtime" orm:"column(createtime)" json:"createtime"`
	LastModifyTime string `form:"lastmodifytime" orm:"column(lastmodifytime)" json:"lastmodifytime"`
}

type UserDataConfig struct {
	Id           int64 `form:"id" orm:"column(id)" json:"id"`
	UId          int64 `form:"uid" orm:"column(uid)" json:"uid"`
	DataConfigId int64 `form:"data_config_id" orm:"column(id)" json:"id"`
}

func (t *DataConfig) TableName() string {
	return "data_config"
}

func init() {
	orm.RegisterModel(new(DataConfig))
}

func ClearDataCache() error {
	return dataconfigcache.ClearAll()
}
func ClearDataCacheByDataType(dataType string) (err error) {
	//先删除全部的
	ClearDataConfigCacheByDataType(dataType)
	//单个删除
	datas, err := GetDataConfigByDataType(dataType)
	if err != nil {
		return
	}

	for _, v := range datas {
		err = ClearDataConfigCacheById(v.Id)
		if err != nil {
			if err.Error() == "key not exist" {
				continue
			} else {
				return
			}
		} else {
			continue
		}
	}
	return nil
}
func AddDataConfig(m *DataConfig) (id int64, err error) {
	o := orm.NewOrm()
	id, err = o.Insert(m)
	if err == nil {
		m.Id = id
		ClearDataConfigCacheByDataType(m.DataType)
		key := datacachePrefix + strconv.FormatInt(id, 10)
		n := *m
		dataconfigcache.Put(key, n, cachTime)
	}
	return
}
func ClearDataConfigCacheById(id int64) error {
	key := datacachePrefix + strconv.FormatInt(id, 10)
	err := dataconfigcache.Delete(key)
	return err
}
func ClearDataConfigCacheByDataType(datatype string) error {
	dtkey := datacachePrefix + datatype
	err := dataconfigcache.Delete(dtkey)
	return err
}
func ClearDataConfigCachByDataID(dataId string) (err error) {
	key := datacachePrefix + dataId
	err = dataconfigcache.Delete(key)
	return
}
func GetDataConfigById(id int64) (v DataConfig, err error) {
	key := datacachePrefix + strconv.FormatInt(id, 10)
	if dataconfigcache.IsExist(key) {
		pconfig := dataconfigcache.Get(key)
		v = pconfig.(DataConfig)
		err = nil
	} else {
		o := orm.NewOrm()
		v1 := &DataConfig{Id: id}
		if err = o.Read(v1); err == nil {
			v = *v1
			dataconfigcache.Put(key, v, cachTime)
		}
	}
	return
}
func GetDataConfigByCreator(creator string, data_type string,useCache bool) (v []*DataConfig, err error) {
	key := datacachePrefix + "_" + creator + "_" + data_type
	if useCache == true{
		if dataconfigcache.IsExist(key) {
			pconfig := dataconfigcache.Get(key)
			v = pconfig.([]*DataConfig)
			err = nil
		}else {
			o := orm.NewOrm()
			_, err = o.Raw("select * from data_config where creator=?", creator).QueryRows(&v)
			if err == nil && v != nil {
				dataconfigcache.Put(key, v, cachTime)
			}
		}
	} else {
		o := orm.NewOrm()
		_, err = o.Raw("select * from data_config where creator=?", creator).QueryRows(&v)
	}
	return
}
func GetDataConfigByDataType(dataType string) (v []*DataConfig, err error) {
	key := datacachePrefix + dataType
	if dataconfigcache.IsExist(key) {
		pconfig := dataconfigcache.Get(key)

		v = pconfig.([]*DataConfig)
		if v == nil {
			o := orm.NewOrm()
			_, err = o.Raw("select * from data_config where data_type=? order by data_no asc", dataType).QueryRows(&v)
			if err == nil && v != nil {
				dataconfigcache.Put(key, v, cachTime)
			}
		} else {
			err = nil
		}
	} else {
		o := orm.NewOrm()
		_, err = o.Raw("select * from data_config where data_type=? order by data_no asc", dataType).QueryRows(&v)
		if err == nil {
			dataconfigcache.Put(key, v, cachTime)
		}
	}
	return
}
func GetAlgorithms() (algorithms []map[string]interface{}, err error) {
	configStr, err := GetDataJsonByDataType("algorithm")
	if err != nil {
		return nil, err
	}
	err = ffjson.Unmarshal([]byte(configStr), &algorithms)
	return
}

func GetAlByAlID(aid string) string {
	Als, err := GetAlgorithms()
	if err != nil {
		return ""
	}
	for _, v := range Als {
		if v["AID"].(string) == aid {
			return v["AIName"].(string)
		}
	}
	return ""
}
func GetDataJsonByDataType(datatype string) (s string, err error) {
	datas, err := GetDataConfigByDataType(datatype)
	var b bytes.Buffer
	if err == nil {
		b.WriteString("[")
		for k, v := range datas {
			b.WriteString(v.DataJson)
			if k < len(datas)-1 {
				b.WriteString(",")
			}
		}
		b.WriteString("]")
	}
	s = b.String()
	return
}

func UpdateDataConfigById(m *DataConfig) (err error) {
	o := orm.NewOrm()
	v := DataConfig{Id: m.Id}
	if err = o.Read(&v); err == nil {
		var num int64
		m.CreateTime = v.CreateTime
		m.Creator = v.Creator
		if num, err = o.Update(m); err == nil {
			ClearDataConfigCacheByDataType(m.DataType)
			ClearDataConfigCacheById(m.Id)
			key := datacachePrefix + strconv.FormatInt(m.Id, 10)
			dataconfigcache.Put(key, *m, cachTime)
			fmt.Println("Number of records updated in database:", num)
		}
	}
	return
}

func OpenSql() *sql.DB {
	var err error
	dbsrc := beego.AppConfig.String("MYSQL::dbsrc")
	host := beego.AppConfig.String("MYSQL::host")
	database := beego.AppConfig.String("MYSQL::CAMS")
	db, err := sql.Open("mysql", dbsrc+"@tcp("+host+")/"+database)
	if err != nil {
		os.Exit(0)
	}
	return db
}
func UpdateDataConfigByType(m *DataConfig) (err error) {
	db := OpenSql()
	defer db.Close()
	ds, _ := GetDataConfigByDataType(m.DataType)
	for _, subData := range ds {
		ClearDataConfigCacheById(subData.Id)
	}
	ClearDataConfigCacheByDataType(m.DataType)
	o := orm.NewOrm()
	var v []*DataConfig
	_, err = o.Raw("select * from data_config where data_type=?", m.DataType).QueryRows(&v)
	if err == nil && len(v) > 0 {
		_, err = db.Exec("UPDATE `data_config` SET `data_json` = ?,`lastmodifytime`= ? where `data_type` = ? ", m.DataJson, m.LastModifyTime,
			m.DataType)
		if err == nil {
			fmt.Println("UpdateDataConfigByType success:" + m.DataType)
		}
	} else {
		_, err = db.Exec(" INSERT INTO `data_config` (`data_json`, `data_type`,`createtime`) VALUES (?, ?,?)", m.DataJson, m.DataType, time.Now().Format("2006-01-02 15:04:05"))
		if err == nil {
			fmt.Println("insertDataConfigByType success:" + m.DataType)
		}
	}

	return
}
func DeleteDataConfig(id int64) (err error) {
	o := orm.NewOrm()
	v := DataConfig{Id: id}
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&DataConfig{Id: id}); err == nil {
			ClearDataConfigCacheById(id)
			ClearDataConfigCacheByDataType(v.DataType)
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}
func GetAllDataConfig(fields []string) (l []*DataConfig, err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(DataConfig))

	if _, err = qs.All(&l, fields...); err != nil {
		return nil, err
	}
	return
}

func GetDataConfigData(tableName string) (ds []*interface{}, err error) {
	o := orm.NewOrm()
	_, err = o.Raw("SELECT * FROM " + tableName).QueryRows(&ds)
	return
}
